﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Linq;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using MyLib.IO;
using MyLib.Web.Properties;

namespace MyLib.Web.UI {
	/// <summary>
	/// 
	/// </summary>
	[DefaultProperty("FileType")]
	[Designer(typeof(MyPlaceholderDesigner))]
	[ToolboxData("<{0}:MyViewFiles runat=\"server\"></{0}:MyViewFiles>")]
	public class MyViewFiles : DataBoundControl, INamingContainer {
		/// <summary>
		/// 
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("~/File.axd")]
		public string DownloadUrl { get; set; }

		/// <summary>
		/// 
		/// </summary>
		[Category("Appearance")]
		[Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
		[UrlProperty]
		public string PreviewImageUrl { get; set; }

		private IList<FileObject> m_files;

		/// <summary>
		/// 
		/// </summary>
		protected override HtmlTextWriterTag TagKey {
			get {
				return HtmlTextWriterTag.Ul;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(System.EventArgs e) {
			base.OnInit(e);

			Page.RegisterRequiresControlState(this);
		}

		/// <summary>
		/// 
		/// </summary>
		protected override void PerformSelect() {
			// Call OnDataBinding here if bound to a data source using the
			// DataSource property (instead of a DataSourceID), because the
			// databinding statement is evaluated before the call to GetData.       
			if (!IsBoundUsingDataSourceID) {
				OnDataBinding(EventArgs.Empty);
			}

			var data = GetData();
			if (data != null) {
				// The GetData method retrieves the DataSourceView object from  
				// the IDataSource associated with the data-bound control.
				data.Select(CreateDataSourceSelectArguments(), OnDataSourceViewSelectCallback);

				// The PerformDataBinding method has completed.
				RequiresDataBinding = false;
				MarkAsDataBound();

				// Raise the DataBound event.
				OnDataBound(EventArgs.Empty);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="retrievedData"></param>
		private void OnDataSourceViewSelectCallback(IEnumerable retrievedData) {

			// Call OnDataBinding only if it has not already been 
			// called in the PerformSelect method.
			if (IsBoundUsingDataSourceID) {
				OnDataBinding(EventArgs.Empty);
			}
			// The PerformDataBinding method binds the data in the  
			// retrievedData collection to elements of the data-bound control.
			PerformDataBinding(retrievedData);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="retrievedData"></param>
		protected override void PerformDataBinding(IEnumerable retrievedData) {
			base.PerformDataBinding(retrievedData);

			// If the data is retrieved from an IDataSource as an 
			// IEnumerable collection, attempt to save its values to file list.
			if (retrievedData != null) {

				foreach (object dataItem in retrievedData) {
					var ofile = dataItem as FileObject;

					if (ofile == null)
						continue;

					m_files.Add(ofile);
				}
			}
		}

		/// <summary>
		/// 
		/// </summary>
		protected override void CreateChildControls() {
			base.CreateChildControls();

			Controls.Clear();

			if (DesignMode) {
				var dd = new Literal();
				dd.Text = "[" + ID + "]";
				Controls.Add(dd);
				return;
			}

			var form = this.Page.Form;
			if ((form != null) && (string.IsNullOrWhiteSpace(form.Enctype))) {
				form.Enctype = "multipart/form-data";
			}

			var durl = ResolveUrl(DownloadUrl.Trim());

			var seq = 0;
			foreach (var ofile in m_files) {
				// Skip special file(s).
				if (ofile.Name.StartsWith("__"))
					continue;

				var item = new WebControl(HtmlTextWriterTag.Li);
				item.ID = "Item" + seq;

				var lnk = new HyperLink();
				lnk.ID = "DownloadFile" + seq;
				lnk.NavigateUrl = DownloadUrl + "?file_id=" + ofile.Id;
				lnk.ToolTip = string.Format(Main.FileClickToDownload, ofile.Name);
				lnk.Text = ofile.Name.AbbreviatedTo();

				var ibt1 = new ImageButton();
				ibt1.ID = "PreviewFile" + seq;
				ibt1.CssClass = "previewFile";
				ibt1.ImageUrl = PreviewImageUrl;
				ibt1.ImageAlign = ImageAlign.AbsMiddle;
				ibt1.AlternateText = Main.FilePreview;
				ibt1.CausesValidation = false;
				ibt1.ToolTip = Main.FilePreview + " [" + ofile.Name + "]";

				item.Controls.Add(lnk);

				var ext = System.IO.Path.GetExtension(ofile.Name);
				if (string.IsNullOrEmpty(ext)) {
					// Do nothing.
				} else {
					ext = ext.ToLower();

					if (ext == ".txt" || ext == ".text" || ext == ".c" || ext == ".cpp" || ext == ".pas" ||
						ext == ".java" || ext == ".cs" || ext == ".vb" || ext == ".py" || ext == ".sql") {
						ibt1.OnClientClick = string.Format("return myViewFiles_previewTxtFile('{0}', '{1}', '{2}', '{3}');",
							this.ClientID,
							this.ResolveClientUrl(DownloadUrl + "?file_id=" + ofile.Id),
							ofile.Name.EncodeJsString(),
							ofile.Name.AbbreviatedTo().EncodeJsString());

						item.Controls.Add(ibt1);
					} else if (ext == ".png" || ext == ".gif" || ext == ".jpg" || ext == ".jpeg" ||
						ext == ".bmp" || ext == ".tif" || ext == ".ico" || ext == ".icon") {
						ibt1.OnClientClick = string.Format("return myViewFiles_previewImgFile('{0}', '{1}', '{2}', '{3}');",
							this.ClientID,
							this.ResolveClientUrl(DownloadUrl + "?file_id=" + ofile.Id),
							ofile.Name.EncodeJsString(),
							ofile.Name.AbbreviatedTo().EncodeJsString());

						item.Controls.Add(ibt1);
					}
				}

				Controls.Add(item);

				++seq;
			} // end of foreach.

			if (seq == 0) {
				var item = new WebControl(HtmlTextWriterTag.Li);
				item.ID = "None";
				item.CssClass = "none";

				var lit = new Literal();
				lit.ID = "LitNone";
				lit.Text = Properties.Main.FileNone;
				lit.Mode = LiteralMode.Encode;
				item.Controls.Add(lit);

				Controls.Add(item);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="savedState"></param>
		protected override void LoadViewState(object savedState) {
			var states = savedState as object[];

			base.LoadViewState(states[0]);

			var files = states[1] as FileObject[];
			if (files != null) {
				m_files = new List<FileObject>(files);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		protected override object SaveViewState() {
			object baseState = base.SaveViewState();

			FileObject[] files = null;
			if (m_files != null && m_files.Count != 0)
				files = m_files.ToArray();

			return new object[] { baseState, files };
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="savedState"></param>
		protected override void LoadControlState(object savedState) {
			object[] stateLastRequest = (object[])savedState;

			// Grab the state for the base class
			// and give it to it.
			object baseState = stateLastRequest[0];
			base.LoadControlState(baseState);

			// Now load this control’s state.
			this.DownloadUrl = (string)stateLastRequest[1];
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		protected override object SaveControlState() {
			// Grab the state for the base control.
			object baseState = base.SaveControlState();

			// Create an array to hold the base control’s state
			// and this control’s state.
			object thisState = new object[] { baseState, DownloadUrl };
			return thisState;
		}

		/// <summary>
		/// 
		/// </summary>
		public MyViewFiles() {
			m_files = new List<FileObject>();

			DownloadUrl = "~/File.axd";

			PreviewImageUrl = "~/Common_Images/previewFile.png";
		}
	} // end of ViewFiles.
}
